package com.zt.english.adapter

import android.content.Intent
import android.graphics.Color
import android.graphics.Paint
import android.graphics.drawable.ColorDrawable
import android.text.Spannable
import android.text.SpannableString
import android.text.style.BackgroundColorSpan
import android.text.style.ForegroundColorSpan
import android.util.TypedValue
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.liveData
import androidx.lifecycle.viewModelScope
import androidx.recyclerview.widget.RecyclerView
import cn.jzvd.Jzvd
import cn.jzvd.JzvdStd
import com.zt.english.R
import com.zt.english.activity.audio.AudioPlayViewModel
import com.zt.english.activity.audio.YouDaoRepository
import com.zt.english.activity.word.WordInfoActivity
import com.zt.english.bean.SubtitlesBean
import com.zt.english.bean.TextTranslateBean
import com.zt.english.databinding.ItemSubtitlesBinding
import com.zt.english.player.AudioPlayerController
import com.zt.english.player.WordPlayerController
import com.zt.english.utils.SystemUtil
import com.zt.english.utils.ToasUtils
import com.zt.english.utils.TranslateUtil
import com.zt.english.utils.WordUtil
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch

/**
 * recycleview字幕列表适配器（databinding版）
 */
class SubtitleRecycleAdapter(val playType : PlayTypeEnum,val ctx:AppCompatActivity,val datas : List<SubtitlesBean>,val youDaoRepository: YouDaoRepository): RecyclerView.Adapter<SubtitleRecycleAdapter.DataBindingViewModel>() {
    var isGoWordInfoAty = false
    private val wordUtil:WordUtil
    init{
        wordUtil = WordUtil(ctx)
    }
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DataBindingViewModel {
        val itemView = LayoutInflater.from(parent.context).inflate(R.layout.item_subtitles, parent, false)
        return DataBindingViewModel(itemView)
    }

    override fun getItemCount(): Int  = datas.size

    override fun onBindViewHolder(holder: DataBindingViewModel, position: Int) {
        holder.bind(datas.get(position),position)
    }

    //内部类
    inner class DataBindingViewModel(itemView :View): RecyclerView.ViewHolder(itemView){
        private val itemBinding: ItemSubtitlesBinding by lazy {
            ItemSubtitlesBinding.bind(itemView)
        }
        fun bind(bean : SubtitlesBean,position: Int){
            itemBinding.bean = bean
            itemBinding.listener = View.OnClickListener {
                itemClickListener?.itemClick(position,bean)
            }
            handlerWord(bean,position)
        }

        /**
         * 单词空格拆分，添加到单行linearlayout,单行linearlayout在添加到根itemBinding.rootEnglish
         */
        private fun handlerWord(bean : SubtitlesBean,position: Int){
            val words = bean.contentEn.split(" ")

            val pageWidth = wordUtil.chapterPageWidth
            val lineHeight = wordUtil.chapterLineHeight
            var remainingWidth = pageWidth

            //移除所有子view,解决item内容重复问题
            itemBinding.rootEnglish.removeAllViews()

            //创建包含每一行单词的linearlayout
            var lineLinearlayout = LinearLayout(ctx)
            lineLinearlayout.setLayoutParams(ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT))
            //将一行单词的linearlayout添加到根Linearlayout
            itemBinding.rootEnglish.addView(lineLinearlayout)

            for (word in words){
                val tv  = createWordTextView(bean.reading.get()?:false,word,position)
                var wordWidth: Int?//单个单词宽
                if (word == "\n") {
                    wordWidth = pageWidth
                } else {
                    wordWidth = wordUtil.getStringWidth2(tv!!)
                }
                if(remainingWidth < wordWidth){
                    //创建新行
                    lineLinearlayout = LinearLayout(ctx)
                    lineLinearlayout.setLayoutParams(ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT))
                    //将新行添加到rootEnglish
                    itemBinding.rootEnglish.addView(lineLinearlayout)
                    //重置剩余行宽
                    remainingWidth = pageWidth
                }
                //将tv单词添加到行lineLinearlayout
                lineLinearlayout.addView(tv)
                //剩余宽度自减
                remainingWidth -= wordWidth
            }
        }
        //创建正常单词tv
        private fun createWordTextView(reading :Boolean,word: String, position: Int): TextView? {
            val aword = TextView(ctx)
            aword.text = word
            aword.setTextSize(TypedValue.COMPLEX_UNIT_PX, wordUtil.chapterFontSize.toFloat())
            if(reading){
                aword.setTextColor(ctx.resources.getColor(R.color.color_focus_word))
            }else{
                aword.setTextColor(ctx.resources.getColor(R.color.color_normal_word))
            }
            aword.paint.flags = Paint.FAKE_BOLD_TEXT_FLAG
            aword.paint.isAntiAlias = true
            //设置lp布局参数
            val width: Int
            width = if (word == "\n") {
                ViewGroup.LayoutParams.MATCH_PARENT
            } else {
                wordUtil.getStringWidth2(aword)
            }
            aword.layoutParams = ViewGroup.LayoutParams(width, ViewGroup.LayoutParams.WRAP_CONTENT)

            //设置点击事件
            aword.setOnClickListener{
                /**
                 * 当前点击的tv背景着色：https://www.jianshu.com/p/1d17c2daf59b
                 * 判断word是否以, ; . ? " ."结尾
                 */
                val end:Int
                if(word.endsWith(",") || word.endsWith(";") || word.endsWith(".") || word.endsWith("?") || word.endsWith( '"')){
                    val mark = "." + '"' //以."结尾
                    if(word.endsWith(mark)){
                        end = word.length-2
                    }else{
                        end = word.length-1
                    }
                }else{
                    end = word.length
                }

                /**
                 * 请求文本翻译api
                 */
                val reallyWord = word.substring(0,end)
                val map = TranslateUtil.parameters(reallyWord)

                //liveData()内部实现了协程的封装
                liveData<TextTranslateBean>{
                    youDaoRepository.translateTxt(map)
                        .catch {
                            ToasUtils.show("当前网络链接不给力，请稍后再试")
                        }
                        .collectLatest {
                            //需发射，Observer接口才会回调
                            emit(it)
                        }
                }.observe(ctx, Observer {
                    /**
                     * 设置字体背景
                     */
                    val spanString = SpannableString(word)
                    //再构造一个改变字体背景的Span
                    val spanBackground = BackgroundColorSpan(Color.BLUE)
                    spanString.setSpan(spanBackground, 0, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
                    //再构造一个改变字体颜色的Span
                    val spanColor = ForegroundColorSpan(Color.WHITE)
                    spanString.setSpan(spanColor, 0, end, Spannable.SPAN_EXCLUSIVE_INCLUSIVE)
                    aword.text = spanString
                    /**
                     * popupwindow弹框
                     */
                    showPopupWindow(aword,word,position,end,it)
                })
            }
            return aword
        }
    }
    /**
     * 2句代码：实现指定position item距顶部一定位置且有滚动效果。
     * 若不加notifyItemChanged(position,datas.get(position))则很僵硬的直接定位到某一位置。此句代码主要是用于实现words字幕读取时颜色变化
     * manager.scrollToPositionWithOffset(lastPosition,getHeight()) + notifyItemChanged(position,datas.get(position))
     */
    private var lastPosition:Int = 0
    fun read(position:Int){
        //去除重复大量相同item位置的UI更新
        if(position>0 && lastPosition==position)return

        //更新item bena数据，databinding自动刷新item布局引用
        datas.get(lastPosition).reading.set(false)
        datas.get(position).reading.set(true)

        //更新item，从而实现words字幕读取时颜色变化效果(2参数解决列表item更新高度显示bug问题)
        notifyItemChanged(lastPosition,datas.get(lastPosition))
        notifyItemChanged(position,datas.get(position))

        lastPosition = position
    }
    fun visibilityEnCh(mode : EnumVisi){
        if(datas.size<1)return
        when(mode){
            EnumVisi.ALL -> {
                for (bean in datas){
                    bean.enShow.set(true)
                    bean.chShow.set(true)
                }
            }
            EnumVisi.EN -> {
                for (bean in datas){
                    bean.enShow.set(true)
                    bean.chShow.set(false)
                }
            }
            EnumVisi.CH -> {
                for (bean in datas){
                    bean.enShow.set(false)
                    bean.chShow.set(true)
                }
            }
            EnumVisi.NONE -> {
                for (bean in datas){
                    bean.enShow.set(false)
                    bean.chShow.set(false)
                }
            }
        }
    }
    enum class EnumVisi{
        ALL,
        EN,
        CH,
        NONE
    }
    enum class PlayTypeEnum{
        AUDIO,
        VIDEO
    }
    /**
     * PopWindow坐标位置显示的两种方法：
     *
     * popupWindow.showAtLocation(view,gravity,x,y)
     * 参一：activity里的任意view,用于为下面的popupWindow提供坐标计算
     * 参二：popupWindow的位置相对原点
     * 参三，四：popupWindow相对原点的想x,y坐标
     *
     * popupWindow.showAsDropDown(view,x,y)
     * 参一：popupWindow对view的左下角为相对位置原点
     * 参二，三：popupWindow对相对原点的x,y坐标
     *
     * view?.getLocationInWindow(location)
     * 获取view在屏幕中的坐标(屏幕左上角为坐标原点，坐标为view的左上角)
     */
    private var isPlayPopWindowBefore :Boolean = false//popupwindow弹出之前音频是否是播放状态
    fun showPopupWindow(
        aword: TextView,
        word: String,
        position: Int,
        end: Int,
        data: TextTranslateBean
    ) {
        if(playType==PlayTypeEnum.AUDIO){
            //暂停音频播放
            if(AudioPlayerController.get().isPlaying()){
                isPlayPopWindowBefore = true
                AudioPlayerController.get().pause()
            }else{
                isPlayPopWindowBefore = false
            }
        }else if (playType==PlayTypeEnum.VIDEO){
            //暂停视频播放
            JzvdStd.goOnPlayOnPause()
        }
        /**
         * 布局视图
         */
        val reallyWord = word.substring(0,end)
        val contentView = LayoutInflater.from(ctx).inflate(R.layout.layout_pop_word, null)
        val triangleUp = contentView.findViewById<ImageView>(R.id.triangle_up)
        val triangleDown = contentView.findViewById<ImageView>(R.id.triangle_down)
        val wordTv = contentView.findViewById<TextView>(R.id.word_tv)
        val descTv = contentView.findViewById<TextView>(R.id.desc_tv)
        val seeDetailTv = contentView.findViewById<TextView>(R.id.see_detail_tv)
        //标题
        wordTv.text = reallyWord
        //音标
        val ukphoneticTv = contentView.findViewById<TextView>(R.id.ukphonetic_tv)
        val usphoneticTv = contentView.findViewById<TextView>(R.id.usphonetic_tv)
        ukphoneticTv.text = "英/"+ data.basic?.ukphonetic+"/"
        usphoneticTv.text = "美/"+ data.basic?.usphonetic+"/"
        //详情介绍
        val explains =  data.basic?.explains
        val sb = StringBuilder()
        if (explains != null) {
            for(desc in explains){
                sb.append(desc).append("\n")
            }
            descTv.text = sb.toString()
        }
        /**
         * 重新测量高度
         */
        contentView.measure(0,0)

        //布局视图高度计算
        val upImageHeight = triangleUp.measuredHeight
        val dowmImageHeight = triangleDown.measuredHeight
        val wordTvHeight = wordTv.measuredHeight
        val phoneticTvHeight = ukphoneticTv.measuredHeight
        val descTvHeight = descTv.measuredHeight
        val seeDetailTvHeight = seeDetailTv.measuredHeight

        //布局视图真实高度
        val contentViewReallyHeight:Int  = (upImageHeight + dowmImageHeight + wordTvHeight+ phoneticTvHeight + descTvHeight + seeDetailTvHeight + 1f + SystemUtil.dp2px(50f)).toInt()

        //popupwindow高度设置
        val popHeight = contentViewReallyHeight


        /**
         * PopWindow
         */
        val popupWindow = PopupWindow(contentView)
        popupWindow.isFocusable = true
        //设置宽高
        popupWindow.setWidth(SystemUtil.getDisplayMetrics(ctx).widthPixels - SystemUtil.dp2px(30f))
        popupWindow.setHeight(popHeight)
        //设置一个背景解决,某些手机窗体dismiss失败
        popupWindow.setBackgroundDrawable(ColorDrawable())
        popupWindow.setOutsideTouchable(true)
        popupWindow.setOnDismissListener(PopupWindow.OnDismissListener {
            /**
             * 弹框关闭后恢复textview样式
             */
            val spanString = SpannableString(word)
            val spanBackground = BackgroundColorSpan(Color.TRANSPARENT)
            spanString.setSpan(spanBackground, 0, word.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
            val color:Int
            if(position==lastPosition){ //点击的单词为当前音频播放行
                color = ctx.resources.getColor(R.color.color_focus_word)
            }else{
                color = ctx.resources.getColor(R.color.color_normal_word)
            }
            val spanColor = ForegroundColorSpan(color)
            spanString.setSpan(spanColor, 0,word.length, Spannable.SPAN_EXCLUSIVE_INCLUSIVE)
            aword.text = spanString

            /**
             * 音频or视频状态恢复
             */
            if(playType==PlayTypeEnum.AUDIO){
                if(isPlayPopWindowBefore && !isGoWordInfoAty)AudioPlayerController.get().play()
            }else if(playType==PlayTypeEnum.VIDEO){
                JzvdStd.goOnPlayOnResume()
            }
        })

        //获取view在屏幕中的坐标(屏幕左上角为坐标原点，坐标为view的左上角)
        val location = IntArray(2)
        aword.getLocationInWindow(location)
        //view高度-状态栏高度-顶部标题栏高度
        val remainHeight = location[1] - SystemUtil.getStateBarHeight(ctx) - SystemUtil.dp2px(45f)
        if(remainHeight > popHeight){
            triangleUp.visibility = View.INVISIBLE
            triangleDown.visibility = View.VISIBLE
            popupWindow.showAtLocation(aword,Gravity.START and  Gravity.TOP,SystemUtil.dp2px(15f),location[1] - popHeight)
        }else{
            triangleUp.visibility = View.VISIBLE
            triangleDown.visibility = View.INVISIBLE
            val viewHeight = aword.height
            popupWindow.showAtLocation(aword,Gravity.START and  Gravity.TOP,SystemUtil.dp2px(15f),location[1] + viewHeight)
        }
        val wordViewWidth = aword.width
        /**
         * 三角位置通过设置其lp的leftMargin值来实现三角位置偏移
         */
        val lpUp = triangleUp.layoutParams as RelativeLayout.LayoutParams
        val lpDown = triangleDown.layoutParams as RelativeLayout.LayoutParams

        val leftMarginUp = location[0] - SystemUtil.dp2px(15f) + (wordViewWidth-wordUtil.chapterWordSapce)/2 - triangleUp.measuredWidth/2
        val rightMarginDown = location[0] - SystemUtil.dp2px(15f) + (wordViewWidth-wordUtil.chapterWordSapce)/2 - triangleDown.measuredWidth/2

        if(leftMarginUp < SystemUtil.dp2px(8f)){ //8dp为圆角半径大小
            lpUp.leftMargin = SystemUtil.dp2px(8f)
        }else{
            lpUp.leftMargin = leftMarginUp
        }
        if(rightMarginDown < SystemUtil.dp2px(8f)){ //8dp为圆角半径大小
            lpDown.leftMargin = SystemUtil.dp2px(8f)
        }else{
            lpDown.leftMargin = rightMarginDown
        }
        //查看完整解析
        seeDetailTv.setOnClickListener {
            isGoWordInfoAty = true
            popupWindow.dismiss()
            val intent = Intent(ctx,
                WordInfoActivity::class.java)
            ctx.startActivityForResult(intent,100)
        }
        //英式音标发音
        if(data.basic?.ukspeech!=null){
            contentView.findViewById<ImageView>(R.id.uk_iv).setOnClickListener {
                WordPlayerController.get().startPlay(data.basic.ukspeech)
            }
        }
        //美式音标发音
        if(data.basic?.usspeech != null){
            contentView.findViewById<ImageView>(R.id.us_iv).setOnClickListener {
                WordPlayerController.get().startPlay(data.basic.usspeech)
            }
        }
        WordPlayerController.get().registerCallback(object : WordPlayerController.Callbacks{
            override fun onPlaybackStateChanged(state: WordPlayerController.PlaybackState?) {
                when (state) {
                    WordPlayerController.PlaybackState.PLAYBACK_STATE_PLAYING ->{
                        ToasUtils.show("start")
                    }
                    WordPlayerController.PlaybackState.PLAYBACK_STATE_COMPLETION ->{
                        ToasUtils.show("complete")
                    }
                    else -> {

                    }
                }
            }
            override fun onAudioDataChanged(duration: Int) {
                ToasUtils.show("时长：" + duration)
            }
        })
    }
    //单词析义界面返回
    fun result(){
        isGoWordInfoAty = false
        if(isPlayPopWindowBefore)AudioPlayerController.get().play()
    }

    /**
     * 列表item点击回掉接口
     */
    interface ItemClickListener{
        fun itemClick(position:Int,bean: SubtitlesBean)
    }
    var itemClickListener:ItemClickListener?=null
}